{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /root/anaconda3/envs/mytf/lib/python3.8/site-packages/tensorflow/python/compat/v2_compat.py:96: disable_resource_variables (from tensorflow.python.ops.variable_scope) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "non-resource variables are not supported in the long term\n"
     ]
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import tensorflow.compat.v1 as tf\n",
    "%matplotlib inline\n",
    "tf.disable_v2_behavior()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "class SOM:\n",
    "    def __init__(self,width,height,dim):\n",
    "        self.num_iters=100\n",
    "        self.width=width\n",
    "        self.height=height\n",
    "        self.dim=dim\n",
    "        self.node_locs=self.get_locs()\n",
    "    \n",
    "        nodes=tf.Variable(tf.random_normal([width*height,dim]))\n",
    "        self.nodes=nodes\n",
    "        \n",
    "        x=tf.placeholder(tf.float32,[dim])\n",
    "        iter=tf.placeholder(tf.float32)\n",
    "        \n",
    "        self.x=x\n",
    "        self.iter=iter\n",
    "        \n",
    "        bmu_loc=self.get_bmu_loc(x)\n",
    "        self.propagate_nodes=self.get_propagation(bmu_loc,x,iter)\n",
    "        \n",
    "    def get_propagation(self,bmu_loc,x,iter):\n",
    "        num_nodes=self.width*self.height\n",
    "        rate=1.0-tf.div(iter,self.num_iters)\n",
    "        alpha=rate*0.5\n",
    "        sigma=rate*tf.to_float(tf.maximum(self.width,self.height))/2.\n",
    "        expanded_bmu_loc=tf.expand_dims(tf.to_float(bmu_loc),0)\n",
    "        sqr_dists_from_bmu=tf.reduce_sum(tf.square(tf.subtract(\n",
    "            expanded_bmu_loc,self.node_locs)),1)\n",
    "        neigh_factor=tf.exp(-tf.div(sqr_dists_from_bmu,2*tf.square(sigma)))\n",
    "        rate=tf.multiply(alpha,neigh_factor)\n",
    "        rate_factor=tf.stack([tf.tile(tf.slice(rate,[i],[1]),\n",
    "                             [self.dim]) for i in range(num_nodes)])\n",
    "        nodes_diff=tf.multiply(rate_factor,\n",
    "                              tf.subtract(tf.stack([x for i in range(num_nodes)]\n",
    "                                                  ),self.nodes))\n",
    "        update_nodes=tf.add(self.nodes,nodes_diff)\n",
    "        return tf.assign(self.nodes,update_nodes)\n",
    "    \n",
    "    def get_bmu_loc(self,x):\n",
    "        expanded_x=tf.expand_dims(x,0)\n",
    "        sqr_diff=tf.square(tf.subtract(expanded_x,self.nodes))\n",
    "        \n",
    "        dists=tf.reduce_sum(sqr_diff,1)\n",
    "        bmu_idx=tf.argmin(dists,0)\n",
    "        bmu_loc=tf.stack([tf.mod(bmu_idx,self.width),tf.div(bmu_idx,self.width)])\n",
    "        return bmu_loc\n",
    "    \n",
    "    def get_locs(self):\n",
    "        #locs=[[x,y] \n",
    "        #       for y in range(self.height)\n",
    "        #       for x in range(self.width)]\n",
    "        locs=[]\n",
    "        for y in range(self.height):\n",
    "            for x in range(self.width):\n",
    "                locs.append([x,y])\n",
    "                \n",
    "        return tf.to_float(locs)\n",
    "    \n",
    "    def train(self,data):\n",
    "        with tf.Session() as sess:\n",
    "            sess.run(tf.global_variables_initializer())\n",
    "            for i in range(self.num_iters):\n",
    "                for data_x in data:\n",
    "                    sess.run(self.propagate_nodes,feed_dict={self.x:data_x,self.iter:i})\n",
    "            centroid_grid=[[] for i in range(self.width)]\n",
    "            self.nodes_val=list(sess.run(self.nodes))\n",
    "            self.locs_val=list(sess.run(self.node_locs))\n",
    "            for i,l in enumerate(self.locs_val):\n",
    "                centroid_grid[int(l[0])].append(self.nodes_val[i])\n",
    "            self.centroid_grid = centroid_grid\n",
    "            \n",
    "            \n",
    "        \n",
    "            \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQcAAAD8CAYAAAB6iWHJAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/d3fzzAAAACXBIWXMAAAsTAAALEwEAmpwYAAANLUlEQVR4nO3df6hf9X3H8efLLKJER1biZpqkWljo6ArTNE0VYbiuDg2C/UNG/KMWGVwqdliYf5QNHPtvfxUmKboLlRoo7QRbF7p0xRVHlc7VNCSZmroFJxgMTaM2MUTU2Pf++B7l7vq5+fU93/O9N/f5gC/3nO/53O/78yXhdc/3nPM971QVkjTfRdOegKTFyXCQ1GQ4SGoyHCQ1GQ6SmgwHSU2/Nc4vJ/kI8E/A1cDLwJ9X1RuNcS8DbwLvAaeqavM4dSVN3rh7Dl8DflxVG4Efd+sL+ZOqusZgkJaGccPhNuCRbvkR4Atjvp6kRSLjXCGZ5NdVtXrO+htV9TuNcf8LvAEU8I9VNXua15wBZgBYxaf5xHlPb/HKhXuo5w/qN9OewkSsyrRnMBkvvwxHj1bz3Z3xmEOSfwOubGz6m3OYww1V9WqS3wWeSPKLqvpJa2AXHLMA+XSKn55DlaXi4kunPYOJ+da7J6c9hYnYsvLC/JrBZz6z8LYzhkNVfX6hbUl+mWRtVR1OshY4ssBrvNr9PJLk+8AWoBkOkhaHcfdvdwJf6pa/BPzz/AFJViW5/P1l4M+A58asK2nCxg2HvwduSvI/wE3dOkk+mmRXN+b3gKeT7AN+BvxLVf3rmHUlTdhY1zlU1WvAnzaefxXY2i2/BPzROHUkDe/CPWwuaSyGg6Qmw0FSk+EgqclwkNRkOEhqMhwkNRkOkpoMB0lNhoOkJsNBUpPhIKnJcJDUZDhIajIcJDUZDpKaDAdJTYaDpKZewiHJzUleTHIwyYe6XmXkgW77/iSb+qgraXLGDockK4BvALcAnwTuSPLJecNuATZ2jxngwXHrSpqsPvYctgAHq+qlqnoH+C6jNnlz3QbsqJFngNVdnwtJi1Qf4bAOeGXO+qHuuXMdI2kR6SMcWn325vcOO5sxo4HJTJLdSXbzq7HnJuk89REOh4ANc9bXA6+exxhg1CuzqjZX1Wau6GF2ks5LH+HwLLAxyceTXAxsY9Qmb66dwJ3dWYvrgGNVdbiH2pImZKyOVwBVdSrJV4AfASuAh6vq+SRf7rY/BOxi1AHrIHASuGvcupIma+xwAKiqXYwCYO5zD81ZLuCePmpJGoZXSEpqMhwkNRkOkpoMB0lNhoOkJsNBUpPhIKnJcJDUZDhIajIcJDUZDpKaDAdJTYaDpCbDQVKT4SCpyXCQ1GQ4SGoyHCQ1GQ6SmobqlXljkmNJ9naP+/uoK2lyxr7B7JxemTcx6k/xbJKdVfXCvKFPVdWt49aTNIw+7j79Qa9MgCTv98qcHw7nri6Cdy8Z+2UWm8uPXjrtKUzMRx59Z9pTmIyT7057BpNxmu4xQ/XKBLg+yb4kP0zyhwu92P9rh3e02TFP0gD62HM4mz6Ye4CrqupEkq3A48DG1otV1SwwC5BNK0wHaUoG6ZVZVcer6kS3vAtYmWRND7UlTcggvTKTXJkk3fKWru5rPdSWNCFD9cq8Hbg7ySngLWBb1yJP0iI1VK/M7cD2PmpJGoZXSEpqMhwkNRkOkpoMB0lNhoOkJsNBUpPhIKnJcJDUZDhIajIcJDUZDpKaDAdJTYaDpCbDQVKT4SCpyXCQ1GQ4SGoyHCQ19dUO7+EkR5I8t8D2JHmga5e3P8mmPupKmpy+9hy+Bdx8mu23MOpTsRGYAR7sqa6kCeklHKrqJ8DrpxlyG7CjRp4BVidZ20dtSZMx1DGHs22ZZzs8aZEYKhzOpmXe6Mmq2araXFWbWdP6NUlDGCocztgyT9LiMlQ47ATu7M5aXAccq6rTNP+WNG29dLxK8h3gRmBNkkPA3wIr4YPOV7uArcBB4CRwVx91JU1OX+3w7jjD9gLu6aOWpGF4haSkJsNBUpPhIKnJcJDUZDhIajIcJDUZDpKaDAdJTYaDpCbDQVKT4SCpyXCQ1GQ4SGoyHCQ1GQ6SmgwHSU2Gg6Qmw0FS01Dt8G5McizJ3u5xfx91JU1OL/eQZNQObzuw4zRjnqqqW3uqJ2nChmqHJ2mJ6WvP4Wxcn2Qfo2Y291XV861BSWYYNduFbICPNoctaasueXnaU5iYtW/dMO0pTEa9O+0ZTMZbC28aKhz2AFdV1YkkW4HHGXXc/pCqmgVmAbJik80ypSkZ5GxFVR2vqhPd8i5gZZI1Q9SWdH4GCYckVyZJt7ylq/vaELUlnZ+h2uHdDtyd5BSjTznbui5YkhapodrhbWd0qlPSEuEVkpKaDAdJTYaDpCbDQVKT4SCpyXCQ1GQ4SGoyHCQ1GQ6SmgwHSU2Gg6Qmw0FSk+EgqclwkNRkOEhqMhwkNRkOkpoMB0lNY4dDkg1JnkxyIMnzSe5tjEmSB5IcTLI/yaZx60qarD7uIXkK+Kuq2pPkcuDnSZ6oqhfmjLmFUZ+KjcBngQe7n5IWqbH3HKrqcFXt6ZbfBA4A6+YNuw3YUSPPAKuTrB23tqTJ6fWYQ5KrgWuB/5y3aR3wypz1Q3w4QN5/jZkku5Pspo72OT1J56C3cEhyGfAY8NWqOj5/c+NXmn0rqmq2qjZX1WZsiiVNTS/hkGQlo2D4dlV9rzHkELBhzvp6Rg11JS1SfZytCPBN4EBVfX2BYTuBO7uzFtcBx6rq8Li1JU1OH2crbgC+CPxXkr3dc38NfAw+aIe3C9gKHAROAnf1UFfSBI0dDlX1NO1jCnPHFHDPuLUkDccrJCU1GQ6SmgwHSU2Gg6Qmw0FSk+EgqclwkNRkOEhqMhwkNRkOkpoMB0lNhoOkJsNBUpPhIKnJcJDUZDhIajIcJDUZDpKahmqHd2OSY0n2do/7x60rabKGaocH8FRV3dpDPUkDGKodnqQlpo89hw+cph0ewPVJ9jFqZnNfVT2/wGvMADOjtY/B25f1OcVF4ZdvXj3tKUzM6xdol7JV9fa0pzAh7y64pbdwOEM7vD3AVVV1IslW4HFGHbc/pKpmgVmAXLS52TJP0uQN0g6vqo5X1YlueRewMrlA/8RIF4hB2uElubIbR5ItXd3Xxq0taXKGaod3O3B3klPAW8C2rguWpEVqqHZ424Ht49aSNByvkJTUZDhIajIcJDUZDpKaDAdJTYaDpCbDQVKT4SCpyXCQ1GQ4SGoyHCQ1GQ6SmgwHSU2Gg6Qmw0FSk+EgqclwkNRkOEhq6uMGs5ck+VmSfV07vL9rjEmSB5IcTLI/yaZx60qarD5uMPs28LmuJ8VK4OkkP6yqZ+aMuYVRn4qNwGeBB7ufkhapPtrh1fs9KYCV3WP+naVvA3Z0Y58BVidZO25tSZPTV1ObFd1t6Y8AT1TV/HZ464BX5qwfwn6a0qLWSzhU1XtVdQ2wHtiS5FPzhrRuXd/sW5FkJsnuJLupX/UxPUnnodezFVX1a+DfgZvnbToEbJizvp5RQ93Wa8xW1eaq2kyu6HN6ks5BH2crrkiyulu+FPg88It5w3YCd3ZnLa4DjlXV4XFrS5qcPs5WrAUeSbKCUdg8WlU/SPJl+KAd3i5gK3AQOAnc1UNdSRPURzu8/cC1jecfmrNcwD3j1pI0HK+QlNRkOEhqMhwkNRkOkpoMB0lNhoOkJsNBUpPhIKnJcJDUZDhIajIcJDUZDpKaDAdJTYaDpCbDQVKT4SCpyXCQ1GQ4SGoyHCQ1DdUr88Ykx5Ls7R73j1tX0mQN1SsT4KmqurWHepIG0Mfdpws4U69MSUtMH3sOdD0rfg78PvCNRq9MgOuT7GPU6eq+qnp+gdeaAWa61RO8c9GLfczxLKwBjg5RaODkHOx9AVw13Jsb9H0NbMj3dtVCGzL6w9+PrvPV94G/rKrn5jz/28Bvuo8eW4F/qKqNvRXuQZLdVbV52vPom+9r6Vks722QXplVdbyqTnTLu4CVSdb0WVtSvwbplZnkyiTplrd0dV8bt7akyRmqV+btwN1JTgFvAduqz88z/Zid9gQmxPe19CyK99brMQdJFw6vkJTUZDhIalr24ZDk5iQvJjmY5GvTnk9fkjyc5EiS5848eulIsiHJk0kOdJfr3zvtOfXhbL6GMPiclvMxh+4g6n8DNwGHgGeBO6rqhalOrAdJ/pjRlas7qupT055PX5KsBdZW1Z4klzO6+O4LS/3frDubt2ru1xCAextfQxjMct9z2AIcrKqXquod4LvAbVOeUy+q6ifA69OeR9+q6nBV7emW3wQOAOumO6vx1cii+hrCcg+HdcArc9YPcQH8R1suklwNXAu0LtdfcpKsSLIXOAI8scDXEAaz3MMhjeeW7+esJSTJZcBjwFer6vi059OHqnqvqq4B1gNbkkz14+ByD4dDwIY56+sZfTFMi1j3mfwx4NtV9b1pz6dvC30NYWjLPRyeBTYm+XiSi4FtwM4pz0mn0R24+yZwoKq+Pu359OVsvoYwtGUdDlV1CvgK8CNGB7YeXeir5EtNku8A/wF8IsmhJH8x7Tn15Abgi8Dn5txZbOu0J9WDtcCTSfYz+qP1RFX9YJoTWtanMiUtbFnvOUhamOEgqclwkNRkOEhqMhwkNRkOkpoMB0lN/wdWIguFwmDDqwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "colors=np.array(\n",
    "[[0.,0.,1.],\n",
    "[0.,0.,0.95],\n",
    "[0.,0.05,1.],\n",
    "[0.,1.,0.],\n",
    "[0.,0.95,0.],\n",
    "[0.,1.,0.05],\n",
    "[1.,0.,0.],\n",
    "[1.,0.05,0.],\n",
    "[1.,0.,0.05],\n",
    "[1.,1.,0.]])\n",
    "som=SOM(4,4,3)\n",
    "som.train(colors)\n",
    "\n",
    "plt.imshow(som.centroid_grid)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
